perm filename BIN[G,BGB]1 blob sn#032397 filedate 1973-06-26 generic text, type T, neo UTF8
00100	TITLE BIN	BODY INTERSECTION - 7 MARCH 1973.
00200	
00300		EXTERN VCW,VCCW,ECCW,VERIFY
00400		EXTERN FACOEF,ESPLIT,INVERT
00500		EXTERN GLUEE,LINKED,MKEV,MKFE
00600		EXTERN MKB,MKF,MKV,MKFRAME
00700		EXTERN OTHER,EVERT,FCCW,FCW
00800		EXTERN DPYBUF,DPYSET,DPYOUT
00900		EXTERN FDPY,EDPY,VDPY
01000	
01100		↓SURBIT←←1B2	;VERTEX ON SURFACE.
01200		↓OKBIT←←2B2
01300	
01400		DEFINE QFACE(Q,V){CDR Q,7(V)}
01500		DEFINE QFACE.(Q,V){DAP Q,7(V)}
01600	
01700		DEFINE NAF (Q,E){CAR Q,-1(E)}
01800		DEFINE NAF.(Q,E){DIP Q,-1(E)}
01900	
02000		DEFINE PAF (Q,E){CDR Q,-1(E)}
02100		DEFINE PAF.(Q,E){DAP Q,-1(E)}
02200	
02300		DEFINE JALT(A,B){ALT. A,B↔ALT. B,A}
02400		DEFINE JALTV(V,V.){ALT. V,V.↔ALT. V.,V
02500		SLACI XWC(V)↔LAPI XWC(V.)↔BLT ZWC(V.)}
02600	
02700		DECLARE{FNEXT,ENEXT}
     

00100	comment/
00200	
00300		Although this code performs body union and body  subtraction;
00400	all  the  nomensclature  will  be in terms of body intersection, BIN.
00500	Pure BIN takes two operand bodies and "copies" off them  a  resultant
00600	body  of their intersection. This requires marking and splitting some
00700	of faces and edges, however the operand bodies  can  be  restored  to
00800	their  original  selves by applying KLTMPS; or if the operands are no
00900	longer needed they must be explicitly killed.
01000	
01100	1. Face-Edge Compare; Make piercing vertices.
01200	
01300		All the faces of each operand is compared with all the edges
01400	of the other. When a edge passes thru a face, the edge is spilt and
01500	a "surface vertex" or "SURV" is placed at the piercing point. The
01600	QFACE of the SURV points at the face pierce.
01700	
01800	2. Face Hole Suppression.
01900	
02000	3. Body and Face Tracing.
02100	
02200	4. Dealing with bodies of parts.
02300	
02400	5. Convex face making.
02500	
02600	
02700	LINKS LEFT BY BIN.
02800	
02900		ALT  of  all result vertices points to a vertex in one or the
03000	other operand. ALT of a result edge is zero, if the edge  was  formed
03100	by  two  conflicting  faces in the operands, the particular faces are
03200	pointed at by the NAF and PAF links. A non-zero ALT of a result edge,
03300	points  at  an  edge  of one operand that was buried inside the solid
03400	body of the other operand, and is thus called an interior edge.
03500	ALT of all faces of the result points at the corresponding face of
03600	one of the operands.
03700	
03800	/
     

00100	SUBR(WITH3D)FACE,XWC,YWC,ZWC--------------------------------------
00200	BEGIN WITH3D; TEST FOR LOCUS WITHIN FACE 3D.
00300		ACCUMULATORS{FLG,V,E,F,DX1,DY1,DZ1,Q1,DX2,DY2,DZ2,Q2,E0}
00400		
00500	;SELECT COMPONENT BY LARGEST FACE COEFFICIENT.
00600		LAC F,ARG4
00700		LACM 1,AA(F)
00800		LACM 2,BB(F)
00900		LACM 3,CC(F)
01000		LACI C0↔CAMG 1,2↔GO[
01100		LACI C1↔CAMG 2,3↔LACI C2↔GO .+3]
01200			CAMG 1,3↔LACI C2↔DAP CASE
01300	
01400	;FIRST EDGE OF THE FACE.
01500		DOM FLG
01600		PED E,F↔DAC E,E0↔SETQ(V,{VCW,E,F})
01700		LAC DX2,XWC(V)↔FSB DX2,ARG3
01800		LAC DY2,YWC(V)↔FSB DY2,ARG2
01900		LAC DZ2,ZWC(V)↔FSB DZ2,ARG1
02000	
02100	L1:	LAC DX1,DX2
02200		LAC DY1,DY2
02300		LAC DZ1,DZ2
02400		LAC Q1,Q2
02500	
02600	;NEXT EDGE OF THE FACE.
02700		SETQ(V,{VCCW,E,F})
02800		SETQ(E,{ECCW,E,F})
02900		LAC DX2,XWC(V)↔FSB DX2,ARG3
03000		LAC DY2,YWC(V)↔FSB DY2,ARG2
03100		LAC DZ2,ZWC(V)↔FSB DZ2,ARG1
03200	
03300	;COMPUTE A COMPONENT OF THE CROSS-PRODUCT.
03400	
03500	CASE:	GO
03600	C0:	LAC 0,DY2↔FMP 0,DZ1↔LAC 1,DY1↔FMP 1,DZ2↔GO C3
03700	C1:	LAC 0,DX1↔FMP 0,DZ2↔LAC 1,DX2↔FMP 1,DZ1↔GO C3
03800	C2:	LAC 0,DX2↔FMP 0,DY1↔LAC 1,DX1↔FMP 1,DY2
03900	C3:	FSB 0,1↔DAC Q2
04000	
04100	;DETECT SIGN CHANGE.
04200	
04300		AOJE FLG,.+3
04400		XOR Q1↔JUMPL POP4J.	;NO SKIP RETURN FALSE.
04500		CAME E,E0↔GO L1
04600		AOS(P)↔POP4J		;SKIP RETURN TRUE.
04700	BEND WITH3D;BGB 7 MARCH 73----------------------------------------
     

00100	SUBR(COMPFE)FACE,EDGE---------------------------------------------
00200	BEGIN COMPFE; COMPARE FACE EDGE 3D FOR PIERCING.
00300	
00400		ACCUMULATORS{X,Y,Z,V1,V2,E,F}
00500	
00600	;CHECK ARGUMENTS FOR FRESHNESS.
00700		LAC E,ARG1↔LAC F,ARG2
00800		NVT V1,E↔PVT V2,E
00900		QFACE 1,V1↔CAMN 1,F↔POP0J
01000		QFACE 1,V2↔CAMN 1,F↔POP0J
01100	
01200	;DIRECTED DISTANCE V1 FROM FACE.
01300		LAC 0,AA(F)↔FMP 0,XWC(V1)
01400		LAC 1,BB(F)↔FMP 1,YWC(V1)↔FAD 0,1
01500		LAC 1,CC(F)↔FMP 1,ZWC(V1)↔FAD 0,1↔DAC Q1#
01600	
01700	;DIRECTED DISTANCE V2 FROM FACE.
01800		LAC 0,AA(F)↔FMP 0,XWC(V2)
01900		LAC 1,BB(F)↔FMP 1,YWC(V2)↔FAD 0,1
02000		LAC 1,CC(F)↔FMP 1,ZWC(V2)↔FAD 0,1↔DAC Q2#
02100	
02200	;DOES EDGE PASS THRU THE PLANE OF THIS FACE.
02300		LAC KK(F)
02400		CAMG Q1↔GO .+3↔CAMLE Q2↔POP0J
02500		CAML Q1↔GO .+3↔CAMGE Q2↔POP0J
02600		FSB 0,Q1↔LAC 1,Q2↔FSB 1,Q1
02700		FDVR 0,1↔SKIPL↔CAMLE[1.0]↔POP0J↔DAC 1
02800	
02900	;SOLVE FOR PLANE PIERCING LOCUS.
03000		LAC X,XWC(V1)↔LAC XWC(V2)↔FSB X↔FMP 1↔FADM X
03100		LAC Y,YWC(V1)↔LAC YWC(V2)↔FSB Y↔FMP 1↔FADM Y
03200		LAC Z,ZWC(V1)↔LAC ZWC(V2)↔FSB Z↔FMP 1↔FADM Z
03300		CALL(WITH3D,F,X,Y,Z)↔POP0J
03400		LAC E,ARG1↔LAC F,ARG2↔ADD P,[XWD 4,4]
03500	
03600	;MAKE FACE PIERCING POINT.
03700		LAC KK(F)↔CAMLE Q1↔GO[CALL(INVERT,E)↔GO .+1]
03800		CALL(ESPLIT,E)↔MARK 1,SURBIT
03900		POP P,ZWC(1)↔POP P,YWC(1)↔POP P,XWC(1)↔POP P,0
04000		QFACE. 0,1↔LAC 2,ARG1↔PED. 2,1↔POP0J
04100	COMMENT .
04200	    V2 ← PVT    ⊗	Q2 < K	   ABOVE F,
04300	                | ENEW
04400	            ____|_____________________
04500	           /    |                    /
04600	          /     ⊗ V      FACE F     /
04700	         /_________________________/
04800			|
04900			|  E
05000	    V1 ← NVT	⊗ 	Q1 > K     BELOW-F.
05100	BEND COMPFE;BGB 7 MARCH 73----------------------------------------
     

00100	SUBR(VNEXT)F,E.,V-------------------------------------------------
00200	BEGIN VNEXT
00300		ACCUMULATORS{F,E.,V}
00400		LAC F,ARG3
00500		LAC E.,ARG2
00600		LAC V,ARG1
00700	
00800	;INTERIOR TO INTERIOR.
00900		ALT 1,E.↔DAC 1,ENEXT
01000		TEST V,SURBIT↔GO[	;SKIP WHEN VERTEX ON SURFACE.
01100			SETQ(ENEXT,{ECCW,ENEXT,F})
01200			CALL(VCCW,ENEXT,F)↔POP3J]
01300	
01400	;SURFACE TO INTERIOR.
01500		QFACE 0,V↔DAC 0,FNEXT
01600		CAME F,FNEXT↔JUMPE 1,[
01700			PED 1,V↔DAC 1,ENEXT
01800			CALL(OTHER,1,V)↔POP3J]
01900	
02000	;INTERIOR TO SURFACE.
02100		DZM ENEXT↔CAME F,FNEXT↔GO[
02200			CALL(OTHERV,F,V)↔POP3J]
02300	
02400	;SURFACE TO SURFACE.
02500		PAF 1,E.↔CAMN 1,F↔NAF 1,E.
02600		PED 0,V↔CALL(OTHER,0,1)↔DAC 1,FNEXT
02700		CALL(OTHERV,FNEXT,V)↔POP3J
02800	BEND VNEXT;BGB 8 MARCH 1973 --------------------------------------
     

00100	SUBR(OTHERV)F,V1 -------------------------------------------------
00200	BEGIN OTHERV
00300		ACCUMULATORS{F1,F2,V1,E,E0}
00400		LAC F2,ARG2
00500		LAC V1,ARG1
00600		QFACE F1,V1
00700	
00800	;DOES F1 PIERCE F2 AT V2.
00900		PED E,F1↔DAC E,E0
01000	L1:	CALL(VCCW,E,F1)
01100		QFACE 0,1
01200		CAMN 0,F2↔POP2J
01300		SETQ(E,{ECCW,E,F1})
01400		CAME E,E0↔GO L1
01500	
01600	;DOES F2 PIERCE F1 AT V2.
01700		PED E,F2↔DAC E,E0
01800	L2:	CALL(VCCW,E,F2)
01900		CAMN 1,V1↔GO .+4
02000		QFACE 0,1
02100		CAMN 0,F1↔POP2J
02200		SETQ(E,{ECCW,E,F2})
02300		CAME E,E0↔GO L2
02400		FATAL(OTHERV)
02500	
02600	COMMENT ;			    OTHER PIERCING VERTEX MANDALA
02700	
02800	  F1 PIERCES F2 AT V2 CASE.	  F2 PIERCES F1 AT V2 CASE.
02900	            ______________                ________
03000	           |              |              |        |
03100	           |   F2         |              |   F2   |
03200	     ______|.........     |        ______|........|_____
03300	    |      ↓        .     |       |      ↓        ↓     |
03400	    | F1   ⊗V1      ⊗V2   |       | F1   ⊗V1      ⊗V2   |
03500	    |_______________↑     |       |_____________________|
03600	           |              |              |        |
03700	           |______________|              |________|     ;
03800	
03900	BEND OTHERV;BGB 8 MARCH 1973 -------------------------------------
     

00100	SUBR(BTRACE)V0 ---------------------------------------------------
00200	BEGIN BTRACE; TRACE THE BODY OF INTERSECTION STARTING FROM V0.
00300		GO L0
00400		ACCUMULATORS{B,F,F.,E,E.,V,V.,V0}
00500		DECLARE{BODYIN,FACE,FACE.,EDGE,EDGE.,VERT,VERT.,VERT0}
00600	
00700	;MAKE THE BODY NODE.
00800	L0:	LAC 1,ARG1↔PED 1,1↔CCW 1,1	;BODY OF V0.
00900		SETQ(BODYIN,{MKB,1})
01000		CALL(MKF,BODYIN)
01100		CALL(MKV,BODYIN)
01200		CALL(MKFRAME)
01300		LAC B,BODYIN
01400		FRAME. 1,B
01500	
01600	;FIRST EDGE OF THE BODY AND ALL ITS FRIENDS.
01700		LAC V0,ARG1
01800		PVT V.,B
01900		JALTV(V0,V.)
02000		PED E,V0
02100		SETQ(F,{FCCW,E,V0})
02200		PFACE F.,B
02300		JALT(F,F.)
02400		SETQ(V,{VCCW,E,F})
02500		LAC[XWD B,BODYIN]↔BLT VERT0	;SAVE AC'S.
02600		SETQ(V.,{MKEV,F.,V.})↔DAC V.,VERT.
02700		LAC V,VERT↔LAC E,EDGE
02800		JALTV(V,V.)
02900		PED E.,V.↔DAC E.,EDGE.
03000		JALT(E,E.)
03100	
     

00100	L1:
00200		SETQ(VERT,{VNEXT,FACE,EDGE.,VERT})
00300		CAME 1,VERT0↔GO L2
00400	
00500	;LAST VERTEX OF THE LAMINA.
00600		ALT 1,1↔SETQ(EDGE.,{MKFE,1,FACE.,VERT.})
00700		LAC E.,EDGE.
00800		SKIPE 1,ENEXT
00900		GO[JALT(1,E.)↔NFACE F.,E.↔DAC F.,FACE.↔GO L3]
01000		LAC 1,FNEXT↔PAF. 1,E.
01100		LAC F,FACE↔NAF. F,E.
01200		NFACE F.,E.↔DAC F.,FACE.↔GO L3
01300	
01400	;NEXT VERTEX OF THE LAMINA.
01500	L2:	SETQ(VERT.,{MKEV,FACE.,VERT.})
01600		LAC V,VERT↔JALTV(V,1)
01700		PED E.,1↔DAC E.,EDGE.
01800		SKIPE 1,ENEXT
01900		GO[JALT(1,E.)↔GO L1]
02000		LAC F,FACE↔PAF. F,E.
02100		LAC 1,FNEXT↔NAF. 1,E.
02200		GO L1
02300	
02400	L3:	CALL(EVERT,BODYIN)
02500	
02600	;TRACE OUT ALL THE FACES CONNECTED TO THIS BODY.
02700	L4:	LAC 1,FACE.
02800		TEST 1,FBIT
02900		GO[LAC 1,BODYIN↔POP1J]		;RETURN THE BODY.
03000		CALL(FTRACE,FACE.)
03100		LAC 1,FACE.
03200		PFACE 1,1
03300		DAC 1,FACE.
03400		GO L4
03500	BEND BTRACE;BGB 8 MARCH 1973 -------------------------------------
     

00100	SUBR(FTRACE)F. ---------------------------------------------------
00200	BEGIN FTRACE; FACE TRACE.
00300		GO L0
00400		DECLARE{F,F.,E,E.,V,V.,U,U.,V0,F2.}
00500	
00600	;GET THE FIRST EDGE AND ITS FRIENDS.
00700	L0:	LAC 1,ARG1↔DAC 1,F.
00800		PED 1,1↔DAC 1,E.
00900		CALL(VCW,E.,F.)↔ALT 1,1↔DAC 1,V0
01000		CALL(VCCW,E.,F.)↔ALT 1,1↔DAC 1,V
01100		LAC 2,E.↔ALT 1,2↔DAC 1,E
01200		JUMPN 1,[
01300			CALL(OTHER,E.,F.)
01400			ALT 1,1
01500			CALL(OTHER,E,1)
01600			GO .+5]
01700		PAF 1,2↔PFACE 0,2
01800		CAME 0,F.↔NAF 1,2
01900		DAC 1,F↔LAC 2,F.
02000		JALT(1,2)
02100	
02200	L1:	
02300		LAC 1,V↔CAMN 1,V0↔POP1J		;EXIT.
02400		DAC 1,U
02500		SETQ(V,{VNEXT,F,E.,V})
02600		SETQ(E.,{ECCW,E.,F.})
02700		SETQ(V.,{VCCW,E.,F.})
02800	
02900	;MAKE SPUR.
03000		LAC 1,V↔ALT 1,1↔JUMPN 1,L2
03100		LAC 1,U↔ALT 1,1
03200		SETQ(V.,{MKEV,F.,1})
03300		LAC 2,V↔JALTV(2,1)
03400		PED 1,1↔DAC 1,E.
03500		SKIPE 2,ENEXT↔GO[JALT(2,1)↔GO L1]
03600		LAC 2,FNEXT↔NAF. 2,1
03700		LAC 2,F↔PAF. 2,1↔GO L1
03800	
03900	;SPLIT FACE.
04000	L2:	CAMN 1,V.↔GO L1		;SKIP V.≠ALT(V).
04100		CALL(LINKED,1,F.)
04200		JUMPE 1,L3		;JUMP WHEN NOT LINKED.
04300	
04400		LAC 1,V↔ALT 1,1
04500		LAC 2,U↔ALT 2,2
04600		SETQ(E.,{MKFE,2,F.,1})
04700		SKIPE 2,ENEXT↔GO[JALT(2,1)↔GO L1]
04800		LAC 2,FNEXT↔NAF. 2,1
04900		LAC 2,F↔PAF. 2,1↔GO L1
05000	
     

00100	;MAKE WASP FACE.
00200	L3:	LAC 1,V↔ALT 1,1↔DAC 1,V.
00300		LAC 1,U↔ALT 1,1↔DAC 1,U.
00400		LAC 1,F.↔PFACE 1,1↔DAC 1,F2.
00500		JUMPE 1,[FATAL({WASP LINK F2.=0.})]
00600		SETQ(E.,{GLUEE,F.,U.,F2.,V.})
00700		SKIPE 2,ENEXT↔GO[JALT(2,1)↔GO L1]
00800		LAC 2,FNEXT↔PAF. 2,1
00900		LAC 2,F↔NAF. 2,1
01000		GO L1
01100	BEND FTRACE;BGB 8 MARCH 1973 -------------------------------------
     

00100	SUBR(BIN)B1,B2----------------------------------------------------
00200	BEGIN BIN; COMPUTE BODY OF INTERSECTION.
00300	
00400		LAC 1,ARG2↔TEST 1,BBIT↔POP2J↔CALL(FACOEF,1,[0])
00500		LAC 1,ARG1↔TEST 1,BBIT↔POP2J↔CALL(FACOEF,1,[0])
00600		LAC 1,ARG2↔PVT 1,1↔TEST 1,VBIT↔GO .+3↔DZM ZPP(1)↔GO .-5
00700		LAC 1,ARG1↔PVT 1,1↔TEST 1,VBIT↔GO .+3↔DZM ZPP(1)↔GO .-5
00800	
00900	;COMPARE ALL THE EDGES OF ONE WITH ALL THE FACES OF THE OTHER.
01000	;THIS N SQUARED PROCESS MAY SOMEDAY BE REPLACED WITH AN OCCULT MODE.
01100		LAC 1,ARG1
01200	L1:	PED 1,1↔TEST 1,EBIT↔GO L2-1
01300		LAC 2,ARG2↔PFACE 2,2↔TESTZ 2,FBIT↔GO[
01400		CALL(COMPFE,2,1)↔POP P,1↔POP P,2↔GO .-3]↔GO L1
01500	
01600		LAC 1,ARG2
01700	L2:	PED 1,1↔TEST 1,EBIT↔GO L3
01800		LAC 2,ARG1↔PFACE 2,2↔TESTZ 2,FBIT↔GO[
01900		CALL(COMPFE,2,1)↔POP P,1↔POP P,2↔GO .-3]↔GO L2
02000	
02100	L3:	CALL(GETSURV,ARG1)↔GO L4
02200		CALL(GETSURV,ARG2)↔GO L4
02300		GO L5
02400	
02500	L4:	CALL(QHOLE,1)		;CHECK OUT A POTENTIAL HOLE.
02600		GO L3			;NO HOLE YET.
02700		CALL(KLSURV,ARG1)	;HOLE FACE WAS PYRAMID'ED.
02800		CALL(KLSURV,ARG2)	;START OVER.
02900		GO BIN
03000	L5:	LAC 1,ARG1
03100		NVT 1,1↔TESTZ 1,VBIT↔GO[
03200			TEST 1,SURBIT↔GO .-3
03300			ALT 0,1↔SKIPE↔GO .-3
03400			CALL(BTRACE,1,1)
03500			DAC 1,B#
03600			POP P,1↔GO .-3]
03700	
03800		LAC 1,ARG2
03900		NVT 1,1↔TESTZ 1,VBIT↔GO[
04000			TEST 1,SURBIT↔GO .-3
04100			ALT 0,1↔SKIPE↔GO .-3
04200			CALL(BTRACE,1,1)
04300			POP P,1↔GO .-3]
04400	
04500		LAC 1,B↔POP2J
04600	
04700	BEND BIN;BGB 7 MARCH 73-------------------------------------------
     

00100	SUBR(SOLANG)V ----------------------------------------------------
00200	BEGIN SOLANG; SOLID ANGLE OF A SURFACE VERTEX.
00300		EXTERN ACOS,DISTANCE,TWOPI
00400		ACCUMULATORS{F,V}
00500	
00600		LAC 1,ARG1↔DAC 1,V0
00700		PED 1,1↔DAC 1,E
00800		SETQ(F1,{FCCW,E,V0})↔SETQ(V1,{OTHERV,F1,V0})
00900		SETQ(F2,{FCW,E,V0})↔ SETQ(V2,{OTHERV,F2,V0})
01000	
01100		CALL(DISTANCE,V1,V0)↔PUSH P,1		;L1
01200		CALL(DISTANCE,V2,V0)↔PUSH P,1		;L2
01300		CALL(DISTANCE,V1,V2)↔FMPR 1,1↔MOVNS 1	;L3
01400	
01500	;ANGLE ← ACOS((L1*L1 + L2*L2 - L3*L3)/(2*L1*L2)).
01600		POP P,2↔POP P,3
01700		LAC 2↔FMPR 3↔FSC 1
01800		FMPR 2,2↔FMPR 3,3
01900		FADR 1,2↔FADR 1,3
02000		FDVR 1,0
02100		CALL(ACOS,1)↔PUSH P,1
02200	
02300		LAC V,V2↔LAC F,F1
02400		LAC 0,XWC(V)↔FMPR 0,AA(F)
02500		LAC 1,YWC(V)↔FMPR 1,BB(F)↔FADR 0,1
02600		LAC 1,ZWC(V)↔FMPR 1,CC(F)↔FADR 0,1
02700		POP P,1
02800		CAML KK(F)↔POP1J↔MOVNS 1
02900		FADR TWOPI↔POP1J	;REFLEX ANGLE.
03000	DECLARE{V0,V1,V2,E,F1,F2}
03100	BEND SOLANG;BGB 23 MARCH 1972-------------------------------------
     

00100	SUBR(KLSURV)B ----------------------------------------------------
00200	BEGIN KLSURV; KILL SURFACE VERTICES OF A BODY.
00300		EXTERN KLEV
00400		ACCUMULATORS{V}
00500		LAC V,ARG1
00600	L:	NVT V,V↔CAMN V,ARG1↔POP1J
00700		TEST V,SURBIT↔GO L
00800		NVT V,V↔PUSH P,V↔PVT V,V
00900		CALL(KLEV,V)↔POP P,V
01000		GO L+1
01100	BEND KLSURV;BGB 23 MARCH 1972-------------------------------------
01200	
01300	
01400	SUBR(OKSURV)V ----------------------------------------------------
01500	BEGIN OKSURV; MARK A SURFACE LOOP AND MAKE ITS LIST.
01600		V←←2
01700		LAC V,ARG1↔PED 1,V
01800		PFACE 1,1↔DAC 1,FACE#		;FACE BEGLONG TO V.
01900		QFACE 1,V↔DAC 1,OLDQF#		;FACE PIERCED BY V.
02000	L:	MARK V,OKBIT↔PUSH P,V
02100		CALL(OTHERV,FACE,V)		;FOLLOW SURV LOOP ACROSS.
02200		POP P,V
02300		CAMN 1,ARG1↔GO[
02400		SETZ↔ALT2. 0,V↔POP1J]		;NIL AT END OF LIST.
02500		ALT2. 1,V↔DAC 1,V		;OLDE V POINTS AT NEW V.
02600		QFACE 0,V↔LAC 1,FACE		;NEXT FACE.
02700		CAME 0,OLDQF↔LAC 1,OLDQF
02800		DAC 0,OLDQF↔PED 0,V
02900		SETQ(FACE,{OTHER,0,1})
03000		GO L
03100	BEND OKSURV;BGB 23 MARCH 1973-------------------------------------
03200	
03300	
03400	SUBR(GETSURV)B ---------------------------------------------------
03500	BEGIN GETSURV; GET AN UNMARKED SURFACE VERTEX OF A BODY OR SKIP.
03600		LAC 1,ARG1
03700	L:	NVT 1,1
03800		CAMN 1,ARG1
03900		GO[AOS(P)↔POP1J]
04000		TEST 1,SURBIT↔GO L
04100		TESTZ 1,OKBIT↔GO L
04200		POP1J
04300	BEND GETSURV;BGB 23 MARCH 1973------------------------------------
     

00100	SUBR(QHOLE)V------------------------------------------------------
00200	BEGIN QHOLE; DETECT AND PYRAMID POTENTIAL PIERCE HOLES.
00300		EXTERN PYRAMID,PI
00400		V←←2
00500		CALL(OKSURV,ARG1)
00600	;SECOND TIME AROUND - LOOK FOR DIFFERENT Q-FACES.
00700		LAC V,ARG1
00800		QFACE 1,V↔DAC 1,QF#
00900	L1:	ALT2 V,V↔JUMPE V,L2
01000		QFACE 0,V↔CAME 0,QF↔POP1J	;EXIT NO HOLE.
01100		GO L1
01200	L2:	DZM A#↔DZM N#↔DZM X#↔DZM Y#↔DZM Z#
01300	
01400	;THIRD TIME AROUND - TAKE SUM OF SOLID INTERIOR ANGLES.
01500		LAC V,ARG1
01600	L3:	LAC XWC(V)↔FADRM X
01700		LAC YWC(V)↔FADRM Y
01800		LAC ZWC(V)↔FADRM Z
01900		AOS N↔PUSH P,V
02000		CALL(SOLANG,V)↔FADRM 1,A
02100		POP P,V↔ALT2 V,V
02200		SKIPE V↔GO L3
02300	
02400		LAC 0,N↔FLOAT↔DAC 0,N
02500		FSBRI(2.0)↔FMPR PI↔FSBR A
02600	L4:	MOVMS↔CAMGE[0.01]↔POP1J		;EXIT - NO HOLE.
02700		CALL(PYRAMID,QF)
02800		LAC X↔FDVR N↔DAC XWC(1)
02900		LAC Y↔FDVR N↔DAC YWC(1)
03000		LAC Z↔FDVR N↔DAC ZWC(1)
03010		PED 2,1↔DAC 2,3↔DAC 1,4
03020	L5:	MARK 2,DARKEN↔SETQ(2,{ECCW,2,4})↔CAME 2,3↔GO L5
03100		AOS(P)↔POP1J			;SKIP EXIT - HOLE.
03200	BEND QHOLE; 23 MARCH 1973 ----------------------------------------
     

00100	SUBR(BUN)B1,B2----------------------------------------------------
00200	BEGIN BUN;BODY UNION.
00300		CALL(EVERT,ARG1)
00400		CALL(EVERT,ARG2)
00500		CALL(BIN,ARG2,ARG2)
00600		PUSH P,1
00700		CALL(EVERT,1)
00800		POP P,1
01000		POP2J
01100	BEND BUN;BGB 10 MARCH 1973----------------------------------------
01200	
01300	SUBR(BSUB)B1,B2---------------------------------------------------
01400	BEGIN BSUB; BODY SUBTRACTION  BNEW ← B1 - B2.
01500		CALL(EVERT,ARG1)
01600		CALL(BIN,ARG2,ARG2)
01800		POP2J
01900	BEND BSUB;BGB 10 MARCH 1973---------------------------------------
     

00100	SUBR(MKCVEX)F ----------------------------------------------------
00200	BEGIN MKCVEX; MAKE FACES CONVEX.
00300		EXTERN MKFE,KLFE,ECOEF,VCCW,QFEV,ECW
00400		ACCUMULATORS{F,E0,V,CNT,N,S,E,W,YMAX,YMIN,XMAX,XMIN}
00500	;	CALL(GEODPY)↔EXTERN GEODPY
00600	
00700	;GET EXTREMA VERTICES.
00800		LAC F,ARG1↔DAC F,FACE1
00810		TEST F,BBIT↔GO L0
00820	L00:	PFACE F,F↔CAMN F,ARG1↔POP1J
00830		PUSH P,F↔CALL(MKCVEX,F)↔POP P,F↔GO L00
00900	L0:	PED E0,F↔DAC E0,EDGE0
01000		LACI CNT,1
01100		SLACI YMAX,400000
01200		SLACI XMAX,400000
01300		SETCM YMIN,YMAX
01400		SETCM XMIN,XMAX
01500	
01600	L1:	SETQ(V,{VCCW,E0,F})
01700		CAMGE YMAX,YPP(V)↔GO[LAC YMAX,YPP(V)↔LAC N,V↔GO .+1]
01800		CAMGE XMAX,XPP(V)↔GO[LAC XMAX,XPP(V)↔LAC E,V↔GO .+1]
01900		CAMLE YMIN,YPP(V)↔GO[LAC YMIN,YPP(V)↔LAC S,V↔GO .+1]
02000		CAMLE XMIN,XPP(V)↔GO[LAC XMIN,XPP(V)↔LAC W,V↔GO .+1]
02100		SETQ(E0,{ECCW,E0,F})
02200		CAME E0,EDGE0↔AOJA CNT,L1
02300	
02400	;EXIT IF FACE1 IS ALREADY A TRIANGLE.
02500	L1B:	CAIN CNT,3↔POP1J
     

00100		GO L6
00200	
00300	;LOP OFF THE POINT WITH THE SMALLEST ANGLE ≡ LARGEST COSINE.
00400	L5:	LAC V,ARG1↔DAC V,VERT2
00500		SETQ(EDGE1,{ECCW,VERT2,FACE1})
00600		PVT 0,1↔CAMN 0,V↔GO .+3
00700		CALL(INVERT,1)↔NVT 0,1↔DAC VERT3
00800		SETQ(EDGE3,{ECW,VERT2,FACE1})
00900		PVT 0,1↔CAMN 0,V↔GO .+3
01000		CALL(INVERT,1)↔NVT 0,1↔DAC VERT1
01100		CALL(ECOEF,EDGE1)
01200		CALL(ECOEF,EDGE3)
01300		LAC 2,EDGE1↔LAC 3,EDGE3
01400		LAC 1,AA(2)↔FMPR 1,AA(3)
01500		LAC 0,BB(2)↔FMPR 0,BB(3)↔FADR 1,0
01600		LAC 0,ARG1
01700		POP1J
01800	
01900	L6:	CALL(,N,S,E,W)
02000		SETZM TMP
02100		CALL(L5)↔CAMGE 1,TMP↔GO .+3↔DAC VERT0↔DAC 1,TMP
02200		CALL(L5)↔CAMGE 1,TMP↔GO .+3↔DAC VERT0↔DAC 1,TMP
02300		CALL(L5)↔CAMGE 1,TMP↔GO .+3↔DAC VERT0↔DAC 1,TMP
02400		CALL(L5)↔CAMGE 1,TMP↔GO .+3↔DAC VERT0↔DAC 1,TMP
02500		CALL(L5,VERT0)
02600	
02700		SETQ(EDGE2,{MKFE,VERT1,FACE1,VERT3})
02750	 	MARK 1,DARKEN
02800		NFACE 1,1↔DAC 1,FACE2
02900		CALL(ECOEF,EDGE2)
     

00100	;SCAN FACE1'S PERIMETER VERT1 TO VERT3.
00200		DZM QMAX↔DZM VERT4
00300		LAC EDGE2↔DAC EDGE0
00310		LAC 1,EDGE1↔PFACE 0,1↔CAME 0,FACE2↔GO[
00320		CALL(INVERT,EDGE1)↔GO .+1]
00350		LAC 1,EDGE3↔PFACE 0,1↔CAME 0,FACE2↔GO[
00360		CALL(INVERT,EDGE3)↔GO .+1]
00400	L2:	SETQ(EDGE0,{ECCW,EDGE0,FACE1})
00500		SETQ(VERT0,{VCCW,EDGE0,FACE1})
00600		CAMN 1,VERT1↔GO L3
00700	
00800	;TEST FOR VERTEX WITHIN THE TRIANGLE THAT WE ARE ABOUT TO LOP.
00900		CALL(QFEV,FACE2,EDGE2,VERT0)↔JUMPL 1,L2↔DAC 1,TMP
01200		CALL(QFEV,FACE2,EDGE1,VERT0)↔JUMPL 1,L2
01500		CALL(QFEV,FACE2,EDGE3,VERT0)↔JUMPL 1,L2
01600	
01700	;FIND VERTEX WITHIN TRIANGLE, FURTHEST FROM EDGE2.
01800		LACM 1,TMP↔CAMG 1,QMAX↔GO L2
01900		DAC 1,QMAX↔LAC VERT0↔DAC VERT4↔GO L2
02000	
02100	;WHEN TRIANGLE IS UNVIOLATED THEN ITERATE.
02200	L3:	SKIPE VERT4↔GO L4
02300		GO MKCVEX
02400	
02500	;WHEN TRIANGLE HAS BEEN VIOLATED THEN RECURSE.
02600	L4:	CALL(KLFE,EDGE2)
02700		CALL(MKFE,VERT2,FACE1,VERT4)
02750		MARK 1,DARKEN
02800		NFACE 1,1	;START WORKING ON THE NEW FACE.
02900		CALL(MKCVEX,1)
03000		GO MKCVEX	;CONTINUE WORKING ON THE OLDE FACE.
03100	
03200	DECLARE{FACE1,FACE2,TMP,QMAX}
03300	DECLARE{EDGE0,EDGE1,EDGE2,EDGE3}
03400	DECLARE{VERT0,VERT1,VERT2,VERT3,VERT4}
03500	BEND MKCVEX;BGB 23 MARCH 1973-------------------------------------
03600	END